package transforms;

import java.util.ListIterator;

import org.apache.bcel.generic.ClassGen;
import org.objectweb.asm.tree.AbstractInsnNode;
import org.objectweb.asm.tree.ClassNode;
import org.objectweb.asm.tree.FieldInsnNode;
import org.objectweb.asm.tree.InsnNode;
import org.objectweb.asm.tree.IntInsnNode;
import org.objectweb.asm.tree.MethodNode;

import com.rshacking.rhf.files.ClassContainer;
import com.rshacking.rhf.updater.Transform;
import com.rshacking.rhf.updater.hooks.ClassHook;
import com.rshacking.rhf.updater.hooks.HooksList;
import com.rshacking.rhf.updater.instructions.InsnCondition;
import com.rshacking.rhf.updater.instructions.InstructionFinder;

/**
 * 
 * Handles transforms in ClientScript
 * 
 * @author Freddy1990 and Wolf
 */
public class RunScriptTransform extends Transform {

    @Override
    public boolean canActivate(final HooksList hooks, final ClassContainer cc) {
        return new ClassGen(cc.getBCEL()).getConstantPool().lookupUtf8("slow") > 0;
    }

    @Override
    public boolean execute(final HooksList hooks, final ClassContainer cc) {

        ClassHook client = null;
        if (hooks.contains("Client")) {
            client = hooks.get("Client");
        } else {
            client = hooks.add("Client", "client");
        }
        ClassHook chInterface = null;
        ClassHook chPlayer = null;
        ClassHook chPlayerDef = null;
        ClassHook chInteractable = null;
        ClassHook chItemDef = null;
        ClassHook chItemDefLoader = null;
        ClassHook chGEItem = null;
        ClassHook chWorldSub = null;
        ClassHook chWorld = null;
        final ClassHook chAnimableNode = null;

        final ClassNode node = cc.getASM();
        final InsnCondition<AbstractInsnNode> GETSTATIC_I = new InsnCondition<AbstractInsnNode>(
                GETSTATIC) {
            @Override
            public boolean check(final AbstractInsnNode ain) {
                if (ain instanceof FieldInsnNode) {
                    final FieldInsnNode fin = (FieldInsnNode) ain;
                    if (!fin.owner.equals(cc.getName()) && fin.desc.equals("I"))
                        return true;
                }
                return false;
            }
        };
        hooks.add("ClientScript", node.name);
        final ListIterator<?> i = node.methods.listIterator();
        while (i.hasNext()) {
            final MethodNode mn = (MethodNode) i.next();
            final InstructionFinder<AbstractInsnNode> finder = new InstructionFinder<AbstractInsnNode>(
                    mn, true);
            /*if (finder
                    .getNext(InsnCondition.ASM.makeIntCond(SIPUSH, 5624)) != null) {
                //finder.reset(true);

                //final IntInsnNode iin = (IntInsnNode) finder
                //        .getNext(InsnCondition.ASM.makeIntCond(SIPUSH, 5624));
                //if (iin != null) {
                    
                //}
            } else *//*if (finder.getNext(InsnCondition.ASM
                    .makeIntCond(SIPUSH, 5015)) != null) {
                //finder.reset(true);
                
                IntInsnNode iin;
                
                //iin = (IntInsnNode) finder.getNext(InsnCondition.ASM
                //        .makeIntCond(SIPUSH, 5015));
                //if (iin != null) {
                    final FieldInsnNode fin0 = (FieldInsnNode) finder.getNext(InsnCondition.ASM.GETFIELD_L);
                    if (fin0 != null) {
                        if (!hooks.contains("Player")) {
                            hooks.add("Player", fin0.owner);
                        }
                        hooks.get("Player").add("displayName", fin0);
                    }
                //}

                iin = (IntInsnNode) finder.getNext(InsnCondition.ASM
                        .makeIntCond(SIPUSH, 5424));
                if (iin != null) {
                    //System.out.println("5424 found");
                    /*final FieldInsnNode fin = (FieldInsnNode) finder
                            .getNext(InsnCondition.ASM.makeIntCond(ICONST_4, 4));
                    final InsnNode in = (InsnNode) finder.getNext(new InsnCondition<AbstractInsnNode>(ICONST_4) {
                        @Override
                        public boolean check(final AbstractInsnNode arg0) {
                            return (arg0.getOpcode() == ICONST_4);
                        }
                    });
                    FieldInsnNode fin = null;
                    if (in != null) {
                        fin = (FieldInsnNode) finder
                        .getPrev(InsnCondition.ASM.PUTSTATIC_I);
                    }
                    if (fin != null) {
                        /*
                        if (chItemDefLoader == null) {
                            chItemDefLoader = hooks.add("ItemDefLoader",
                                    fin.desc);
                        }
                        client.add("itemDefLoader", fin);
                        
                        if (!hooks.contains("Character")) {
                            hooks.add("Character", fin.owner);
                        }
                    }
                    
                    final IntInsnNode iin2 = (IntInsnNode) finder.getNext(InsnCondition.ASM.makeIntCond(BIPUSH, 10));
                    fin = null;
                    if (iin2 != null) {
                        fin = (FieldInsnNode) finder
                        .getPrev(InsnCondition.ASM.PUTSTATIC_I);
                    }
                    if (fin != null) {
                        /*
                        if (chItemDefLoader == null) {
                            chItemDefLoader = hooks.add("ItemDefLoader",
                                    fin.desc);
                        }
                        client.add("itemDefLoader", fin);
                        
                        if (!hooks.contains("NPC")) {
                            hooks.add("NPC", fin.owner);
                        }
                    }
                }
                iin = (IntInsnNode) finder.getNext(InsnCondition.ASM
                        .makeIntCond(SIPUSH, 5624));
                if (iin != null) {
                    FieldInsnNode fin = (FieldInsnNode) finder
                    .getNext(InsnCondition.ASM.PUTSTATIC_I);
                    if (fin != null) {
                        fin = (FieldInsnNode) fin.getNext();
                        if (chAnimableNode == null) {
                            chAnimableNode = hooks.add("AnimableNode",
                                    fin.owner);
                            /*
                             * chAnimableNode.add("hScroll", fin);
                             
                        }
                    }
                }

            }*/// else if (finder.getNext(InsnCondition.ASM.makeLDCCond("Gap at:")) != null) {
            if (mn.isMethodStatic() && mn.desc.equals("(IZ)V")) {
                /*FieldInsnNode tfin = (FieldInsnNode) finder
                        .getPrev(InsnCondition.ASM.GETFIELD_LA);
                /*if (tfin != null) {
                    if (chInterface == null) {
                        chInterface = hooks.add("Interface", tfin.desc);
                    }
                    chInterface.add("children", tfin);
                }*/
                /*
                FieldInsnNode tfin = (FieldInsnNode) finder
                        .getNext(InsnCondition.ASM.PUTFIELD_I);
                if (tfin != null) {
                    if (chInterface == null) {
                        chInterface = hooks.add("Interface", tfin.owner);
                    }
                    chInterface.add("type", tfin);
                }
                finder
                        .getNext(InsnCondition.ASM
                                .makeLDCCond("Tried to .cc_delete static .active-component!"));
                tfin = (FieldInsnNode) finder
                        .getNext(InsnCondition.ASM.GETFIELD_I);
                if (tfin != null) {
                    if (chInterface == null) {
                        chInterface = hooks.add("Interface", tfin.owner);
                    }
                    chInterface.add("id", tfin);
                }
                // FIXME
                */
                IntInsnNode iin = (IntInsnNode) finder
                        .getNext(InsnCondition.ASM.makeIntCond(SIPUSH, 1001));
                if (iin != null) {
                    FieldInsnNode fin = (FieldInsnNode) finder
                            .getNext(InsnCondition.ASM.PUTFIELD_I);
                    if (fin != null) {
                        if (chInterface == null) {
                            chInterface = hooks.add("Interface", fin.owner);
                        }
                        chInterface.add("width", fin);
                    }
                    fin = (FieldInsnNode) finder
                            .getNext(InsnCondition.ASM.PUTFIELD_I);
                    if (fin != null) {
                        if (chInterface == null) {
                            chInterface = hooks.add("Interface", fin.owner);
                        }
                        chInterface.add("height", fin);
                    }
                }
                iin = (IntInsnNode) finder.getNext(InsnCondition.ASM
                        .makeIntCond(SIPUSH, 1003));
                if (iin != null) {
                    final FieldInsnNode fin = (FieldInsnNode) finder
                            .getNext(InsnCondition.ASM.GETFIELD_Z);
                    if (fin != null) {
                        if (chInterface == null) {
                            chInterface = hooks.add("Interface", fin.owner);
                        }
                        chInterface.add("hidden", fin);
                    }
                }
                iin = (IntInsnNode) finder.getNext(InsnCondition.ASM
                        .makeIntCond(SIPUSH, 1100));
                if (iin != null) {
                    FieldInsnNode fin = (FieldInsnNode) finder
                            .getNext(InsnCondition.ASM.GETFIELD_I);
                    if (fin != null) {
                        if (chInterface == null) {
                            chInterface = hooks.add("Interface", fin.owner);
                        }
                        chInterface.add("hScroll", fin);
                    }
                    fin = (FieldInsnNode) finder
                            .getNext(InsnCondition.ASM.GETFIELD_I);
                    if (fin != null) {
                        if (chInterface == null) {
                            chInterface = hooks.add("Interface", fin.owner);
                        }
                        chInterface.add("maxHScroll", fin);
                    }
                    fin = (FieldInsnNode) finder
                            .getNext(InsnCondition.ASM.GETFIELD_I);
                    if (fin != null) {
                        if (chInterface == null) {
                            chInterface = hooks.add("Interface", fin.owner);
                        }
                        chInterface.add("minHScroll", fin);
                    }
                    finder.getNext(InsnCondition.ASM.GETFIELD_I);
                    finder.getNext(InsnCondition.ASM.GETFIELD_I);
                    finder.getNext(InsnCondition.ASM.GETFIELD_I);
                    fin = (FieldInsnNode) finder
                            .getNext(InsnCondition.ASM.GETFIELD_I);
                    if (fin != null) {
                        if (chInterface == null) {
                            chInterface = hooks.add("Interface", fin.owner);
                        }
                        chInterface.add("vScroll", fin);
                    }
                    fin = (FieldInsnNode) finder
                            .getNext(InsnCondition.ASM.GETFIELD_I);
                    if (fin != null) {
                        if (chInterface == null) {
                            chInterface = hooks.add("Interface", fin.owner);
                        }
                        chInterface.add("maxVScroll", fin);
                    }
                    fin = (FieldInsnNode) finder
                            .getNext(InsnCondition.ASM.GETFIELD_I);
                    if (fin != null) {
                        if (chInterface == null) {
                            chInterface = hooks.add("Interface", fin.owner);
                        }
                        chInterface.add("minVScroll", fin);
                    }
                }
                iin = (IntInsnNode) finder.getNext(InsnCondition.ASM
                        .makeIntCond(SIPUSH, 1101));
                if (iin != null) {
                    final FieldInsnNode fin = (FieldInsnNode) finder
                            .getNext(InsnCondition.ASM.PUTFIELD_I);
                    if (fin != null) {
                        if (chInterface == null) {
                            chInterface = hooks.add("Interface", fin.owner);
                        }
                        chInterface.add("textColor", fin);
                    }
                }
                iin = (IntInsnNode) finder.getNext(InsnCondition.ASM
                        .makeIntCond(SIPUSH, 1105));
                if (iin != null) {
                    final FieldInsnNode fin = (FieldInsnNode) finder
                            .getNext(InsnCondition.ASM.GETFIELD_I);
                    if (fin != null) {
                        if (chInterface == null) {
                            chInterface = hooks.add("Interface", fin.owner);
                        }
                        chInterface.add("textureId", fin);
                    }
                }
                iin = (IntInsnNode) finder.getNext(InsnCondition.ASM
                        .makeIntCond(SIPUSH, 1108));
                if (iin != null) {
                    FieldInsnNode fin = (FieldInsnNode) finder
                            .getNext(InsnCondition.ASM.PUTFIELD_I);
                    if (fin != null) {
                        if (chInterface == null) {
                            chInterface = hooks.add("Interface", fin.owner);
                        }
                        chInterface.add("modelType", fin);
                    }
                    fin = (FieldInsnNode) finder
                            .getNext(InsnCondition.ASM.PUTFIELD_I);
                    if (fin != null) {
                        if (chInterface == null) {
                            chInterface = hooks.add("Interface", fin.owner);
                        }
                        chInterface.add("modelId", fin);
                    }
                }
                iin = (IntInsnNode) finder.getNext(InsnCondition.ASM
                        .makeIntCond(SIPUSH, 1109));
                if (iin != null) {
                    finder.getNext(InsnCondition.ASM.PUTFIELD_I);
                    finder.getNext(InsnCondition.ASM.PUTFIELD_I);
                    FieldInsnNode fin = (FieldInsnNode) finder
                            .getNext(InsnCondition.ASM.PUTFIELD_I);
                    if (fin != null) {
                        if (chInterface == null) {
                            chInterface = hooks.add("Interface", fin.owner);
                        }
                        chInterface.add("modelRotationX", fin);
                    }
                    fin = (FieldInsnNode) finder
                            .getNext(InsnCondition.ASM.PUTFIELD_I);
                    if (fin != null) {
                        if (chInterface == null) {
                            chInterface = hooks.add("Interface", fin.owner);
                        }
                        chInterface.add("modelRotationY", fin);
                    }
                    fin = (FieldInsnNode) finder
                            .getNext(InsnCondition.ASM.PUTFIELD_I);
                    if (fin != null) {
                        if (chInterface == null) {
                            chInterface = hooks.add("Interface", fin.owner);
                        }
                        chInterface.add("modelRotationZ", fin);
                    }
                    fin = (FieldInsnNode) finder
                            .getNext(InsnCondition.ASM.PUTFIELD_I);
                    if (fin != null) {
                        if (chInterface == null) {
                            chInterface = hooks.add("Interface", fin.owner);
                        }
                        chInterface.add("modelZoom", fin);
                    }
                }
                iin = (IntInsnNode) finder.getNext(InsnCondition.ASM
                        .makeIntCond(SIPUSH, 1112));
                if (iin != null) {
                    final FieldInsnNode fin = (FieldInsnNode) finder
                            .getNext(InsnCondition.ASM.GETFIELD_String);
                    if (fin != null) {
                        if (chInterface == null) {
                            chInterface = hooks.add("Interface", fin.owner);
                        }
                        chInterface.add("text", fin);
                    }
                }
                iin = (IntInsnNode) finder.getNext(InsnCondition.ASM
                        .makeIntCond(SIPUSH, 1115));
                if (iin != null) {
                    final FieldInsnNode fin = (FieldInsnNode) finder
                            .getNext(InsnCondition.ASM.PUTFIELD_Z);
                    if (fin != null) {
                        if (chInterface == null) {
                            chInterface = hooks.add("Interface", fin.owner);
                        }
                        chInterface.add("inventoryInterface", fin);
                    }
                }
                iin = (IntInsnNode) finder.getNext(InsnCondition.ASM
                        .makeIntCond(SIPUSH, 1116));
                if (iin != null) {
                    final FieldInsnNode fin = (FieldInsnNode) finder
                            .getNext(InsnCondition.ASM.PUTFIELD_I);
                    if (fin != null) {
                        if (chInterface == null) {
                            chInterface = hooks.add("Interface", fin.owner);
                        }
                        chInterface.add("borderThickness", fin);
                    }
                }
                iin = (IntInsnNode) finder.getNext(InsnCondition.ASM
                        .makeIntCond(SIPUSH, 1117));
                if (iin != null) {
                    final FieldInsnNode fin = (FieldInsnNode) finder
                            .getNext(InsnCondition.ASM.PUTFIELD_I);
                    if (fin != null) {
                        if (chInterface == null) {
                            chInterface = hooks.add("Interface", fin.owner);
                        }
                        chInterface.add("shadowColor", fin);
                    }
                }
                iin = (IntInsnNode) finder.getNext(InsnCondition.ASM
                        .makeIntCond(SIPUSH, 1118));
                if (iin != null) {
                    final FieldInsnNode fin = (FieldInsnNode) finder
                            .getNext(InsnCondition.ASM.PUTFIELD_Z);
                    if (fin != null) {
                        if (chInterface == null) {
                            chInterface = hooks.add("Interface", fin.owner);
                        }
                        chInterface.add("flippedVertically", fin);
                    }
                }
                iin = (IntInsnNode) finder.getNext(InsnCondition.ASM
                        .makeIntCond(SIPUSH, 1119));
                if (iin != null) {
                    final FieldInsnNode fin = (FieldInsnNode) finder
                            .getNext(InsnCondition.ASM.PUTFIELD_Z);
                    if (fin != null) {
                        if (chInterface == null) {
                            chInterface = hooks.add("Interface", fin.owner);
                        }
                        chInterface.add("flippedHorizontally", fin);
                    }
                }
                /*
                 * iin = (IntInsnNode) finder.getNext(
                 * InsnCondition.ASM.makeIntCond(SIPUSH, 1120) ); if (iin !=
                 * null) { FieldInsnNode fin = (FieldInsnNode)
                 * finder.getNext(InsnCondition.ASM.PUTFIELD_I); if (fin !=
                 * null) { if (chInterface == null) chInterface =
                 * hooks.add("Interface", fin.owner);
                 * chInterface.add("maxHScroll", fin); } fin = (FieldInsnNode)
                 * finder.getNext(InsnCondition.ASM.PUTFIELD_I); if (fin !=
                 * null) { if (chInterface == null) chInterface =
                 * hooks.add("Interface", fin.owner);
                 * chInterface.add("maxVScroll", fin); } }
                 */
                iin = (IntInsnNode) finder.getNext(InsnCondition.ASM
                        .makeIntCond(SIPUSH, 1305));
                if (iin != null) {
                    final FieldInsnNode fin = (FieldInsnNode) finder
                            .getNext(InsnCondition.ASM.PUTFIELD_String);
                    if (fin != null) {
                        if (chInterface == null) {
                            chInterface = hooks.add("Interface", fin.owner);
                        }
                        chInterface.add("itemName", fin);
                    }
                }
                iin = (IntInsnNode) finder.getNext(InsnCondition.ASM
                        .makeIntCond(SIPUSH, 1306));
                if (iin != null) {
                    final FieldInsnNode fin = (FieldInsnNode) finder
                            .getNext(InsnCondition.ASM.PUTFIELD_String);
                    if (fin != null) {
                        if (chInterface == null) {
                            chInterface = hooks.add("Interface", fin.owner);
                        }
                        chInterface.add("selectedActionName", fin);
                    }
                }
                iin = (IntInsnNode) finder.getNext(InsnCondition.ASM
                        .makeIntCond(SIPUSH, 1307));
                if (iin != null) {
                    final FieldInsnNode fin = (FieldInsnNode) finder
                            .getNext(InsnCondition.ASM.PUTFIELD_StringA);
                    if (fin != null) {
                        if (chInterface == null) {
                            chInterface = hooks.add("Interface", fin.owner);
                        }
                        chInterface.add("itemActions", fin);
                    }
                }
                /*
                 * iin = (IntInsnNode) finder.getNext(
                 * InsnCondition.ASM.makeIntCond(SIPUSH, 1310) ); if (iin !=
                 * null) { FieldInsnNode fin = (FieldInsnNode)
                 * finder.getNext(InsnCondition.ASM.PUTFIELD_String); if (fin !=
                 * null) { if (chInterface == null) chInterface =
                 * hooks.add("Interface", tfin.owner); chInterface.add("text",
                 * fin); } }
                 */
                iin = (IntInsnNode) finder.getNext(InsnCondition.ASM
                        .makeIntCond(SIPUSH, 1500));
                if (iin != null) {
                    final FieldInsnNode fin = (FieldInsnNode) finder
                            .getNext(InsnCondition.ASM.GETFIELD_I);
                    if (fin != null) {
                        if (chInterface == null) {
                            chInterface = hooks.add("Interface", fin.owner);
                        }
                        chInterface.add("x", fin);
                    }
                }
                iin = (IntInsnNode) finder.getNext(InsnCondition.ASM
                        .makeIntCond(SIPUSH, 1501));
                if (iin != null) {
                    final FieldInsnNode fin = (FieldInsnNode) finder
                            .getNext(InsnCondition.ASM.GETFIELD_I);
                    if (fin != null) {
                        if (chInterface == null) {
                            chInterface = hooks.add("Interface", fin.owner);
                        }
                        chInterface.add("y", fin);
                    }
                }
                iin = (IntInsnNode) finder.getNext(InsnCondition.ASM
                        .makeIntCond(SIPUSH, 1505));
                if (iin != null) {
                    final FieldInsnNode fin = (FieldInsnNode) finder
                            .getNext(InsnCondition.ASM.GETFIELD_I);
                    if (fin != null) {
                        if (chInterface == null) {
                            chInterface = hooks.add("Interface", fin.owner);
                        }
                        chInterface.add("parentId", fin);
                    }
                }
                iin = (IntInsnNode) finder.getNext(InsnCondition.ASM
                        .makeIntCond(SIPUSH, 1701));
                if (iin != null) {
                    FieldInsnNode fin = (FieldInsnNode) finder
                            .getNext(InsnCondition.ASM.GETFIELD_I);
                    if (fin != null) {
                        if (chInterface == null) {
                            chInterface = hooks.add("Interface", fin.owner);
                        }
                        chInterface.add("itemId", fin);
                    }
                    fin = (FieldInsnNode) finder
                            .getNext(InsnCondition.ASM.GETFIELD_I);
                    if (fin != null) {
                        if (chInterface == null) {
                            chInterface = hooks.add("Interface", fin.owner);
                        }
                        chInterface.add("itemStackSize", fin);
                    }
                }
                iin = (IntInsnNode) finder.getNext(InsnCondition.ASM
                        .makeIntCond(SIPUSH, 1702));
                if (iin != null) {
                    final FieldInsnNode fin = (FieldInsnNode) finder
                            .getNext(InsnCondition.ASM.GETFIELD_I);
                    if (fin != null) {
                        if (chInterface == null) {
                            chInterface = hooks.add("Interface", fin.owner);
                        }
                        chInterface.add("itemIndex", fin);
                    }
                }
                finder.reset(true);
                iin = (IntInsnNode) finder.getNext(InsnCondition.ASM
                        .makeIntCond(SIPUSH, 403));
                if (iin != null) {
                    final FieldInsnNode fin = (FieldInsnNode) finder
                            .getNext(InsnCondition.ASM.GETFIELD_L);
                    if (fin != null) {
                        if (chPlayer == null) {
                            chPlayer = hooks.add("Player", fin.owner);
                        }
                        if (chPlayerDef == null) {
                            chPlayerDef = hooks.add("PlayerDef", fin.desc);
                        }
                        chPlayer.add("def", fin);
                    }
                }
                /*
                 * iin = (IntInsnNode) finder.getNext(new
                 * InsnCondition(Opcodes.SIPUSH) {
                 * 
                 * @Override public boolean check(AbstractInsnNode node) {
                 * return ((IntInsnNode) node).operand == 3300; } }); if (iin !=
                 * null) { FieldInsnNode fin = (FieldInsnNode)
                 * finder.getNext(new InsnCondition(Opcodes.GETSTATIC) {
                 * 
                 * @Override public boolean check(AbstractInsnNode ain) {
                 * FieldInsnNode fin = (FieldInsnNode) ain; return
                 * fin.desc.equals("I") && !fin.owner.equals(node.name); } });
                 * if (fin != null) hooks.addField("Client", "getLoopCycle",
                 * fin); }
                 */
                iin = (IntInsnNode) finder.getNext(InsnCondition.ASM
                        .makeIntCond(SIPUSH, 3308));
                if (iin != null) {
                    FieldInsnNode fin = (FieldInsnNode) finder
                            .getNext(InsnCondition.ASM.GETSTATIC_L);
                    if (fin != null) {
                        if (chPlayer == null) {
                            chPlayer = hooks.add("Player", fin.desc);
                        }
                        // client.add("localPlayer", fin); handled by
                        // ClientTransforms
                    }
                    fin = (FieldInsnNode) finder
                            .getNext(InsnCondition.ASM.GETFIELD_B);
                    if (fin != null) {
                        if (chInteractable == null) {
                            chInteractable = hooks.add("Interactable",
                                    fin.owner);
                        }
                        chInteractable.add("plane", fin);
                    }
                    fin = (FieldInsnNode) finder
                            .getNext(InsnCondition.ASM.GETFIELD_I);
                    if (fin != null) {
                        if (chInteractable == null) {
                            chInteractable = hooks.add("Interactable",
                                    fin.owner);
                        }
                        chInteractable.add("x", fin);
                    }
                    fin = (FieldInsnNode) finder
                            .getNext(InsnCondition.ASM.GETFIELD_I);
                    if (fin != null) {
                        if (chInteractable == null) {
                            chInteractable = hooks.add("Interactable",
                                    fin.owner);
                        }
                        chInteractable.add("y", fin);
                    }
                }
                iin = (IntInsnNode) finder.getNext(InsnCondition.ASM
                        .makeIntCond(SIPUSH, 3318));
                if (iin != null) {
                    final FieldInsnNode numberNode = (FieldInsnNode) finder
                            .getNext(InsnCondition.ASM.GETFIELD_I);
                    final FieldInsnNode worldNode = (FieldInsnNode) numberNode
                            .getPrevious();
                    if (worldNode != null) {
                        if (chWorld == null) {
                            chWorld = hooks.add("World", worldNode.desc);
                        }
                        client.add("world", worldNode);
                    }
                    if (numberNode != null) {
                        if (chWorld == null) {
                            chWorld = hooks.add("World", numberNode.desc); // TODO
                                                                           // wat
                        }
                        chWorld.add("id", numberNode);
                    }
                }

                iin = (IntInsnNode) finder.getNext(InsnCondition.ASM
                        .makeIntCond(SIPUSH, 3624));
                if (iin != null) {
                    final FieldInsnNode fin = (FieldInsnNode) finder
                            .getNext(new InsnCondition<AbstractInsnNode>(
                                    GETFIELD) {
                                @Override
                                public boolean check(final AbstractInsnNode ain) {
                                    if (ain instanceof FieldInsnNode) {
                                        final FieldInsnNode fin = (FieldInsnNode) ain;
                                        if (fin.owner.equals(hooks
                                                .get("Player").getOrigName())
                                                && fin.desc
                                                        .equals("Ljava/lang/String;"))
                                            return true;
                                    }
                                    return false;
                                }
                            });
                    if (fin != null) {
                        if (chPlayer == null) {
                            chPlayer = hooks.add("Player", fin.owner);
                        }
                        chPlayer.add("name", fin);
                    }
                }

                iin = (IntInsnNode) finder.getNext(InsnCondition.ASM
                        .makeIntCond(SIPUSH, 3760));
                if (iin != null) {
                    final FieldInsnNode fin = (FieldInsnNode) finder
                            .getPrev(new InsnCondition<AbstractInsnNode>(
                                    GETFIELD) {
                                @Override
                                public boolean check(final AbstractInsnNode ain) {
                                    if (ain instanceof FieldInsnNode) {
                                        final FieldInsnNode fin = (FieldInsnNode) ain;
                                        if (fin.desc.contains("(IZI)V"))
                                            return true;
                                    }
                                    return false;
                                }
                            });
                    if (fin != null) {
                        hooks.add("Model", fin.owner);
                        /*
                         * if (chPlayer == null) chPlayer = hooks.add("Player",
                         * fin.owner); chPlayer.add("displayName", fin);
                         */
                    }
                }
                iin = (IntInsnNode) finder.getNext(InsnCondition.ASM
                        .makeIntCond(SIPUSH, 4206));
                if (iin != null) {
                    FieldInsnNode fin = (FieldInsnNode) finder
                            .getNext(InsnCondition.ASM.GETFIELD_I);
                    if (fin != null) {
                        if (chItemDef == null) {
                            chItemDef = hooks.add("ItemDef", fin.owner);
                        }
                        chItemDef.add("certTemplateId", fin);
                    }
                    fin = (FieldInsnNode) finder
                            .getNext(InsnCondition.ASM.GETFIELD_I);
                    if (fin != null) {
                        if (chItemDef == null) {
                            chItemDef = hooks.add("ItemDef", fin.owner);
                        }
                        chItemDef.add("certId", fin);
                    }
                }

                iin = (IntInsnNode) finder.getNext(InsnCondition.ASM
                        .makeIntCond(SIPUSH, 4207));
                if (iin != null) {
                    final FieldInsnNode fin = (FieldInsnNode) finder
                            .getNext(InsnCondition.ASM.GETFIELD_Z);
                    if (fin != null) {
                        if (chItemDef == null) {
                            chItemDef = hooks.add("ItemDef", fin.owner);
                        }
                        chItemDef.add("members", fin);
                    }
                }
                finder.reset(true);
                iin = (IntInsnNode) finder.getNext(InsnCondition.ASM
                        .makeIntCond(SIPUSH, 3629));
                if (iin != null) {
                    final FieldInsnNode fin = (FieldInsnNode) finder
                            .getNext(GETSTATIC_I);
                    if (fin != null) {
                        client.add("myCountry", fin);
                    }
                }
                iin = (IntInsnNode) finder.getNext(InsnCondition.ASM
                        .makeIntCond(SIPUSH, 3903));
                if (iin != null) {
                    final FieldInsnNode fin = (FieldInsnNode) finder
                            .getNext(InsnCondition.ASM.GETSTATIC_LA);
                    if (fin != null) {
                        if (chGEItem == null) {
                            chGEItem = hooks.add("GEItem", fin.desc);
                        }
                        client.add("GEItems", fin);
                    }
                }
                iin = (IntInsnNode) finder.getNext(InsnCondition.ASM
                        .makeIntCond(SIPUSH, 3904));
                if (iin != null) {
                    FieldInsnNode fin = (FieldInsnNode) finder
                            .getNext(InsnCondition.ASM.GETFIELD_I);
                    if (fin != null) {
                        if (chGEItem == null) {
                            chGEItem = hooks.add("GEItem", fin.owner);
                        }
                        chGEItem.add("id", fin);
                    }
                    fin = (FieldInsnNode) finder
                            .getNext(InsnCondition.ASM.GETFIELD_I);
                    if (fin != null) {
                        if (chGEItem == null) {
                            chGEItem = hooks.add("GEItem", fin.owner);
                        }
                        chGEItem.add("price", fin);
                    }
                }
                iin = (IntInsnNode) finder.getNext(InsnCondition.ASM
                        .makeIntCond(SIPUSH, 3906));
                if (iin != null) {
                    final FieldInsnNode fin = (FieldInsnNode) finder
                            .getNext(InsnCondition.ASM.GETFIELD_I);
                    if (fin != null) {
                        if (chGEItem == null) {
                            chGEItem = hooks.add("GEItem", fin.owner);
                        }
                        chGEItem.add("total", fin);
                    }
                }
                iin = (IntInsnNode) finder.getNext(InsnCondition.ASM
                        .makeIntCond(SIPUSH, 3907));
                if (iin != null) {
                    final FieldInsnNode fin = (FieldInsnNode) finder
                            .getNext(InsnCondition.ASM.GETFIELD_I);
                    if (fin != null) {
                        if (chGEItem == null) {
                            chGEItem = hooks.add("GEItem", fin.owner);
                        }
                        chGEItem.add("transfered", fin);
                    }
                }
                iin = (IntInsnNode) finder.getNext(InsnCondition.ASM
                        .makeIntCond(SIPUSH, 3908));
                if (iin != null) {
                    final FieldInsnNode fin = (FieldInsnNode) finder
                            .getNext(InsnCondition.ASM.GETFIELD_I);
                    if (fin != null) {
                        if (chGEItem == null) {
                            chGEItem = hooks.add("GEItem", fin.owner);
                        }
                        chGEItem.add("spent", fin);
                    }
                }
                iin = (IntInsnNode) finder.getNext(InsnCondition.ASM
                        .makeIntCond(SIPUSH, 4200));
                if (iin != null) {
                    final FieldInsnNode fin = (FieldInsnNode) finder
                            .getNext(InsnCondition.ASM.GETFIELD_String);
                    if (fin != null) {
                        if (chItemDef == null) {
                            chItemDef = hooks.add("ItemDef", fin.owner);
                        }
                        chItemDef.add("name", fin);
                    }
                }
                iin = (IntInsnNode) finder.getNext(InsnCondition.ASM
                        .makeIntCond(SIPUSH, 4201));
                if (iin != null) {
                    final FieldInsnNode fin = (FieldInsnNode) finder
                            .getNext(InsnCondition.ASM.GETFIELD_StringA);
                    if (fin != null) {
                        if (chItemDef == null) {
                            chItemDef = hooks.add("ItemDef", fin.owner);
                        }
                        chItemDef.add("groundActions", fin);
                    }
                }
                iin = (IntInsnNode) finder.getNext(InsnCondition.ASM
                        .makeIntCond(SIPUSH, 4202));
                if (iin != null) {
                    final FieldInsnNode fin = (FieldInsnNode) finder
                            .getNext(InsnCondition.ASM.GETFIELD_StringA);
                    if (fin != null) {
                        if (chItemDef == null) {
                            chItemDef = hooks.add("ItemDef", fin.owner);
                        }
                        chItemDef.add("actions", fin);
                    }
                }
                iin = (IntInsnNode) finder.getNext(InsnCondition.ASM
                        .makeIntCond(SIPUSH, 4203));
                if (iin != null) {
                    final FieldInsnNode fin = (FieldInsnNode) finder
                            .getNext(InsnCondition.ASM.GETFIELD_I);
                    if (fin != null) {
                        if (chItemDef == null) {
                            chItemDef = hooks.add("ItemDef", fin.owner);
                        }
                        chItemDef.add("value", fin);
                    }
                }
                iin = (IntInsnNode) finder.getNext(InsnCondition.ASM
                        .makeIntCond(SIPUSH, 4204));
                if (iin != null) {
                    final FieldInsnNode fin = (FieldInsnNode) finder
                            .getNext(InsnCondition.ASM.GETFIELD_I);
                    if (fin != null) {
                        if (chItemDef == null) {
                            chItemDef = hooks.add("ItemDef", fin.owner);
                        }
                        chItemDef.add("stackable", fin);
                    }
                }
                /*
                 * finder.reset(true); iin = (IntInsnNode) finder.getNext(
                 * InsnCondition.ASM.makeIntCond(SIPUSH, 3612) ); if (iin !=
                 * null) { FieldInsnNode fin = (FieldInsnNode)
                 * finder.getNext(GETSTATIC_I); if (fin != null)
                 * client.add("clanChatPlayerCount", fin); }
                 * 
                 * // TODO unstable?
                 * 
                 * iin = (IntInsnNode)
                 * finder.getNext(InsnCondition.ASM.makeIntCond(SIPUSH, 3613));
                 * 
                 * if (iin != null) { FieldInsnNode fin = (FieldInsnNode)
                 * finder.getNext(new InsnCondition(GETFIELD) {
                 * 
                 * @Override public boolean check(InstructionItem item) { return
                 * ((FieldInsnNode) item).desc.equals("Ljava/lang/String;"); }
                 * }); if (fin != null) { if (chClanChatPlayer == null)
                 * chClanChatPlayer = hooks.add("ClanChatPlayer", fin.owner);
                 * chClanChatPlayer.add("name", fin); } } /*
                 * 
                 * iin = (IntInsnNode) finder.getNext(new
                 * InsnCondition(Opcodes.SIPUSH) {
                 * 
                 * @Override public boolean check(AbstractInsnNode node) {
                 * return ((IntInsnNode) node).operand == 3613; } }); if (iin !=
                 * null) { FieldInsnNode fin = (FieldInsnNode)
                 * finder.getNext(new InsnCondition(Opcodes.GETFIELD) {
                 * 
                 * @Override public boolean check(AbstractInsnNode node) {
                 * return ((FieldInsnNode)
                 * node).desc.equals("Ljava/lang/String;"); } }); if (fin !=
                 * null) { hooks.add("ClanChatPlayer", fin.owner);
                 * hooks.addField("ClanChatPlayer", "getName", fin); } } iin =
                 * (IntInsnNode) finder.getNext(new
                 * InsnCondition(Opcodes.SIPUSH) {
                 * 
                 * @Override public boolean check(AbstractInsnNode node) {
                 * return ((IntInsnNode) node).operand == 3614; } }); if (iin !=
                 * null) { FieldInsnNode fin = (FieldInsnNode)
                 * finder.getNext(icGetIntField); if (fin != null) {
                 * hooks.add("ClanChatPlayer", fin.owner);
                 * hooks.addField("ClanChatPlayer", "getWorld", fin); } } iin =
                 * (IntInsnNode) finder.getNext(new
                 * InsnCondition(Opcodes.SIPUSH) {
                 * 
                 * @Override public boolean check(AbstractInsnNode node) {
                 * return ((IntInsnNode) node).operand == 3615; } }); if (iin !=
                 * null) { FieldInsnNode fin = (FieldInsnNode)
                 * finder.getNext(icGetIntField); if (fin != null) {
                 * hooks.add("ClanChatPlayer", fin.owner);
                 * hooks.addField("ClanChatPlayer", "getRank", fin); } } iin =
                 * (IntInsnNode) finder.getNext(new
                 * InsnCondition(Opcodes.SIPUSH) {
                 * 
                 * @Override public boolean check(AbstractInsnNode node) {
                 * return ((IntInsnNode) node).operand == 3618; } }); if (iin !=
                 * null) { FieldInsnNode fin = (FieldInsnNode)
                 * finder.getNext(new InsnCondition(Opcodes.GETSTATIC) {
                 * 
                 * @Override public boolean check(AbstractInsnNode node) {
                 * return ((FieldInsnNode) node).desc.equals("B"); } }); if (fin
                 * != null) hooks.addField("Client", "getMyClanChatRank", fin);
                 * } iin = (IntInsnNode) finder.getNext(new
                 * InsnCondition(Opcodes.SIPUSH) {
                 * 
                 * @Override public boolean check(AbstractInsnNode node) {
                 * return ((IntInsnNode) node).operand == 3624; } }); if (iin !=
                 * null) { FieldInsnNode fin = (FieldInsnNode)
                 * finder.getNext(new InsnCondition(Opcodes.GETSTATIC) {
                 * 
                 * @Override public boolean check(AbstractInsnNode ain) {
                 * FieldInsnNode fin = (FieldInsnNode) ain; return
                 * fin.desc.startsWith("[L") && !fin.owner.equals(node.name); }
                 * }); if (fin != null) { hooks.add("ClanChatPlayer", fin.desc);
                 * hooks.addField("Client", "getClanChatPlayers", fin); } }
                 * finder.reset(Mode.START); iin = (IntInsnNode)
                 * finder.getNext(new InsnCondition(Opcodes.SIPUSH) {
                 * 
                 * @Override public boolean check(AbstractInsnNode node) {
                 * return ((IntInsnNode) node).operand == 3611; } }); if (iin !=
                 * null) { FieldInsnNode fin = (FieldInsnNode)
                 * finder.getNext(new InsnCondition(Opcodes.GETSTATIC) {
                 * 
                 * @Override public boolean check(AbstractInsnNode node) {
                 * return ((FieldInsnNode)
                 * node).desc.equals("Ljava/lang/String;"); } }); if (fin !=
                 * null) hooks.addField("Client", "getClanChannelOwner", fin); }
                 * iin = (IntInsnNode) finder.getNext(new
                 * InsnCondition(Opcodes.SIPUSH) {
                 * 
                 * @Override public boolean check(AbstractInsnNode node) {
                 * return ((IntInsnNode) node).operand == 3624; } }); if (iin !=
                 * null) { FieldInsnNode fin = (FieldInsnNode)
                 * finder.getNext(new InsnCondition(Opcodes.GETFIELD) {
                 * 
                 * @Override public boolean check(AbstractInsnNode node) {
                 * return ((FieldInsnNode)
                 * node).desc.equals("Ljava/lang/String;"); } }); if (fin !=
                 * null) hooks.addField("ClanChatPlayer", "getUsername", fin); }
                 * iin = (IntInsnNode) finder.getNext(new
                 * InsnCondition(Opcodes.SIPUSH) {
                 * 
                 * @Override public boolean check(AbstractInsnNode node) {
                 * return ((IntInsnNode) node).operand == 3625; } }); if (iin !=
                 * null) { FieldInsnNode fin = (FieldInsnNode)
                 * finder.getNext(new InsnCondition(Opcodes.GETSTATIC) {
                 * 
                 * @Override public boolean check(AbstractInsnNode node) {
                 * return ((FieldInsnNode)
                 * node).desc.equals("Ljava/lang/String;"); } }); if (fin !=
                 * null) hooks.addField("Client", "getClanChannelName", fin); }
                 * iin = (IntInsnNode) finder.getNext(new
                 * InsnCondition(Opcodes.SIPUSH) {
                 * 
                 * @Override public boolean check(AbstractInsnNode node) {
                 * return ((IntInsnNode) node).operand == 3626; } }); if (iin !=
                 * null) { FieldInsnNode fin = (FieldInsnNode)
                 * finder.getNext(new InsnCondition(Opcodes.GETFIELD) {
                 * 
                 * @Override public boolean check(AbstractInsnNode node) {
                 * return ((FieldInsnNode)
                 * node).desc.equals("Ljava/lang/String;"); } }); if (fin !=
                 * null) hooks.addField("ClanChatPlayer", "getServer", fin); } }
                 */
                // TODO end unstable ?
                // ------------------------------------------------
                /*
                 * LdcInsnNode ldc = (LdcInsnNode)
                 * finder.getNext(InsnCondition.ASM.makeLDCCond("bad command"));
                 * if (ldc != null) { finder.reset(true);
                 */
                /*
                 * iin = (IntInsnNode) finder.getNext(
                 * InsnCondition.ASM.makeIntCond(SIPUSH, 5004) );
                 */
                /*
                 * if (iin != null) { FieldInsnNode fin = (FieldInsnNode)
                 * finder.getNext(InsnCondition.ASM.GETSTATIC_StringA); if (fin
                 * != null) client.add("chatMessages", fin); fin =
                 * (FieldInsnNode)
                 * finder.getNext(InsnCondition.ASM.GETSTATIC_IA); if (fin !=
                 * null) client.add("chatTypes", fin); } iin = (IntInsnNode)
                 * finder.getNext( InsnCondition.ASM.makeIntCond(SIPUSH, 5010)
                 * ); if (iin != null) { FieldInsnNode fin = (FieldInsnNode)
                 * finder.getNext(InsnCondition.ASM.GETSTATIC_StringA); if (fin
                 * != null) client.add("chatDisplayNames", fin); } iin =
                 * (IntInsnNode) finder.getNext(
                 * InsnCondition.ASM.makeIntCond(SIPUSH, 5019) ); if (iin !=
                 * null) { FieldInsnNode fin = (FieldInsnNode)
                 * finder.getNext(InsnCondition.ASM.GETSTATIC_StringA); if (fin
                 * != null) client.add("chatNames", fin); }
                 */
                // finder.reset(true);
                /*
                 * iin = (IntInsnNode) finder.getNext(new
                 * InsnCondition(Opcodes.SIPUSH) {
                 * 
                 * @Override public boolean check(AbstractInsnNode node) {
                 * return ((IntInsnNode) node).operand == 5019; } }); if (iin !=
                 * null) { FieldInsnNode fin = (FieldInsnNode)
                 * finder.getNext(new InsnCondition(Opcodes.GETSTATIC) {
                 * 
                 * @Override public boolean check(AbstractInsnNode node) {
                 * return ((FieldInsnNode)
                 * node).desc.equals("[Ljava/lang/String;"); } }); if (fin !=
                 * null) hooks.addField("Client", "getChatNames", fin); }
                 */
                iin = (IntInsnNode) finder.getNext(InsnCondition.ASM
                        .makeIntCond(SIPUSH, 5009));
                if (iin != null) {
                    final FieldInsnNode fin = (FieldInsnNode) finder
                            .getNext(GETSTATIC_I);
                    if (fin != null) {
                        client.add("myPlayerRights", fin);
                    }
                }
                iin = (IntInsnNode) finder.getNext(InsnCondition.ASM
                        .makeIntCond(SIPUSH, 5401));
                if (iin != null) {
                    final FieldInsnNode fin = (FieldInsnNode) finder
                            .getNext(InsnCondition.ASM.GETSTATIC_L);
                    if (fin != null) {
                        if (chItemDefLoader == null) {
                            chItemDefLoader = hooks.add("ItemDefLoader",
                                    fin.desc);
                        }
                        client.add("itemDefLoader", fin);
                    }
                }
                iin = (IntInsnNode) finder.getNext(InsnCondition.ASM
                        .makeIntCond(SIPUSH, 6509));
                if (iin != null) {
                    final FieldInsnNode fin = (FieldInsnNode) finder
                            .getNext(GETSTATIC_I);
                    if (fin != null) {
                        client.add("gameState", fin);
                    }
                }
                finder.reset(true);
                /*
                 * iin = (IntInsnNode) finder.getNext(new
                 * InsnCondition(Opcodes.SIPUSH) {
                 * 
                 * @Override public boolean check(AbstractInsnNode node) {
                 * return ((IntInsnNode) node).operand == 5511; } }); if (iin !=
                 * null) { InsnCondition tmp = new
                 * InsnCondition(Opcodes.GETSTATIC) {
                 * 
                 * @Override public boolean check(AbstractInsnNode ain) {
                 * FieldInsnNode fin = (FieldInsnNode) ain; return
                 * fin.desc.equals("I") && !fin.owner.equals(node.name); } };
                 * FieldInsnNode fin = (FieldInsnNode) finder.getNext(tmp); fin
                 * = (FieldInsnNode) finder.getNext(tmp); fin = (FieldInsnNode)
                 * finder.getNext(tmp); fin = (FieldInsnNode)
                 * finder.getNext(tmp); fin = (FieldInsnNode)
                 * finder.getNext(tmp); if (fin != null)
                 * hooks.addField("Client", "getMinimapSetting", fin); }
                 */
                iin = (IntInsnNode) finder.getNext(InsnCondition.ASM
                        .makeIntCond(SIPUSH, 6001));
                if (iin != null) {
                    final FieldInsnNode fin = (FieldInsnNode) finder
                            .getNext(InsnCondition.ASM.PUTSTATIC_Z);
                    if (fin != null) {
                        client.add("flagged", fin);
                    }
                }
                iin = (IntInsnNode) finder.getNext(InsnCondition.ASM
                        .makeIntCond(SIPUSH, 6501));
                if (iin != null) {
                    FieldInsnNode fin = (FieldInsnNode) finder
                            .getNext(InsnCondition.ASM.GETFIELD_I);
                    if (fin != null) {
                        if (chWorldSub == null) {
                            chWorldSub = hooks.add("WorldSub", fin.owner);
                        }
                        chWorldSub.add("id", fin);
                    }
                    /*
                     * fin = (FieldInsnNode)
                     * finder.getNext(InsnCondition.ASM.GETFIELD_I); if (fin !=
                     * null) { if (chWorldSub == null) chWorldSub =
                     * hooks.add("WorldSub", fin.owner); chWorldSub.add("flags",
                     * fin); }
                     */
                    fin = (FieldInsnNode) finder
                            .getNext(InsnCondition.ASM.GETFIELD_String);
                    if (fin != null) {
                        if (chWorldSub == null) {
                            chWorldSub = hooks.add("WorldSub", fin.owner);
                        }
                        chWorldSub.add("activity", fin);
                    }
                }
            }
            // ------------------------------------------------
            /*
             * ldc = (LdcInsnNode)
             * finder.getNext(InsnCondition.ASM.makeLDCCond("event_opbase")); if
             * (ldc != null) { finder.reset(true); FieldInsnNode fin =
             * (FieldInsnNode) finder.getNext(InsnCondition.ASM.GETFIELD_L); if
             * (fin != null) { hooks.add("ScriptParamsNode",
             * fin.owner).add("eventOpBase", fin); hooks.add("EventOpBase",
             * fin.desc); } }
             */
        }
        return true;
    }

}
